Skip to content

test: silence the 8,000-line CI test log — settle the router inside act, stub jsdom's no-ops, quiet the hub's counter feed in tests - #35

Merged
karngyan merged 1 commit into
mainfrom
fix/test-log-noise
Aug 9, 2026
Merged

test: silence the 8,000-line CI test log — settle the router inside act, stub jsdom's no-ops, quiet the hub's counter feed in tests#35
karngyan merged 1 commit into
mainfrom
fix/test-log-noise

Conversation

@karngyan

@karngyan karngyan commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

The noise

The v0.1.0 release run's "Lint and test" step printed ~8,500 log lines, ~95% noise. Measured profile (run 31333105025):

Class Lines Source
React act(...) warnings 736 warnings × 7-line block ≈ 5,150 Transitioner (314), MatchImpl (145), MatchInnerImpl (143), MatchesInner (104) — all TanStack Router internals — plus Root (16), UpdateNotice (8) and a handful of others
jsdom Not implemented: Window's scrollTo() 65 focus mode / Radix scrolling in jsdom
jsdom canvas getContext() 8 the Devices QR canvas in jsdom
relay {"evt":"channel_closed",...} JSON 76 the hub's deliberate Workers Logs counter feed, leaking through relay/test/
jsdom navigation to another Document 3 link-click navigation in jsdom

None of it showed locally because vitest's local default reporter hides console output from passing tests; CI's reporter prints it. pnpm vitest run --reporter=verbose reproduces the CI view exactly (735 warnings locally vs CI's 736), which is what the before/after numbers below are measured with.

The fixes, at their seams

act warnings — fixed in the render helpers, not per-test. Every router-mounting helper did await router.load() and then a bare render(<RouterProvider .../>). Mounting RouterProvider re-runs router.load() from Transitioner's mount effect, and that call's continuations update the router stores a microtask after RTL's synchronous act has exited — one warning per mounted Match, every mount. The helpers now render inside await act(async () => ...) so the post-mount load settles inside act:

  • web/src/testing/render.tsx (renderWithRouter — covers app-shell, session-table, page-header, devices, remote suites)
  • web/src/router.test.tsx (renderAt, renderFleet, renderPicker, renderBare, one inline render)
  • web/src/routes/sessions.test.tsx (mountSessions, plus one attached that starts a navigation)
  • web/src/routes/pair.test.tsx (renderPair, renderRelayPair)
  • web/src/components/app-shell.test.tsx, web/src/components/update-notice.test.tsx: their helpers emitted welcome frames through the synchronous FakeSocket outside act; wrapped.

No global suppression: IS_REACT_ACT_ENVIRONMENT untouched, no console filtering of React output — an act warning from an app component still prints.

jsdom no-ops — stubbed in web/src/testing/test-setup.ts, in the same shape as the existing scrollIntoView stub: window.scrollTo becomes a no-op, HTMLCanvasElement.prototype.getContext returns the null jsdom already returned after logging (the Devices no-canvas fallback test still pins that path).

relay counter line — silenced in tests only. The channel_closed line is production observability (relay/src/hub.ts, retireClient) and stays byte-identical. A new relay/test/setup.ts drops exactly that prefix at the printing edge; everything else the Worker logs still prints. The counters test (test/hub.test.ts, "logs the counters") passes unchanged — its vi.spyOn(console, 'log') wraps the filter and records the call either way.

Before / after

Measured with the reporter mode that matches CI's output (--reporter=verbose, prints passing tests' console output):

Surface Before After
web act warnings 735 (CI: 736) 0
web jsdom noise lines 76 3 (see below)
web total (verbose) 8,661 lines 1,010 lines (≈998 of them the per-test ✓ listing)
web total (default reporter, pnpm vitest run 2>&1 | wc -l) 85 12
relay channel_closed lines 76 0
relay total (verbose) 201 lines 101 lines

Tests: web 56 files / 998 tests, relay 4 files / 90 tests — all passing before and after, none skipped. pnpm run lint (tsc) clean in both; styles.build.test.ts passes (all new comments live in *.test.tsx / src/testing/ / relay/test/, outside the Tailwind scan perimeter).

Deliberately left noisy

  • 3 × jsdom Not implemented: navigation to another Document — the only seam is jsdom's link-click navigation itself, and suppressing it (global preventDefault, anchor click stubs) would change what the anchor-click tests prove: the router-Link-vs-plain-<a href> distinction in testing/render.tsx depends on jsdom not navigating.
  • 1 × workerd's own disconnected: read end of pipe was aborted in the relay run — runtime-internal, not ours to filter.

🤖 Generated with Claude Code

…tub jsdom's no-ops, drop the hub's counter line from test output

The v0.1.0 release run's "Lint and test" step printed ~8,500 lines, ~95%
noise, in four classes. All of it reproduces locally under
vitest --reporter=verbose — the local default reporter hides console
output from passing tests, which is why the suite looked quiet here and
deafening in CI.

- 736 React act(...) warnings (~5,100 lines): every router-mounting
  helper awaited router.load() and then rendered bare. Mounting
  RouterProvider re-runs router.load() from Transitioner's mount effect,
  and its continuations update the router stores a microtask after RTL's
  synchronous act exits — one warning per mounted Match. Fixed at the
  helpers: testing/render.tsx and the per-file mount helpers now render
  inside `await act(async ...)`, so the post-mount load settles inside
  act. Two component helpers (app-shell, update-notice) also emitted
  welcome frames through the synchronous FakeSocket outside act; wrapped.
- 65 lines of jsdom "Not implemented: Window's scrollTo()": no-op stub in
  test-setup.ts, same shape as the existing scrollIntoView stub.
- 8 lines of jsdom canvas getContext(): stubbed to return null, which is
  what jsdom already returned after logging.
- 76 lines of the relay hub's {"evt":"channel_closed",...} JSON: that
  line is the production Workers Logs counter feed and stays; a new
  relay/test/setup.ts drops exactly that prefix from test output. The
  counters test still passes — its console.log spy wraps the filter and
  records the call either way.

Left noisy: 3 jsdom "navigation to another Document" lines, because the
only seam is jsdom's link-click navigation itself and suppressing that
would change what anchor-click tests prove; and workerd's own
"disconnected: read end of pipe was aborted" line in the relay run.

web: 998 tests, relay: 90 tests, all passing before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@karngyan

karngyan commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Confirmed against this PR's own CI run (31334243256), same runner class as the v0.1.0 release run the profile was measured on:

"Lint and test" step v0.1.0 release run this branch
step log lines 8,014 240
act(...) warnings 736 0
channel_closed lines 76 0
scrollTo / getContext lines 65 / 8 0 / 0
web tests 998 passed 998 passed
relay tests 90 passed 90 passed

One caveat worth naming: the first attempt of this run failed on relay/test/hub.test.ts > the handshake deadline > re-arms while unseen clients remain, then reaps them too — the alarm had not re-armed because both clients were already past their 50 ms deadlines when the first alarm ran, i.e. the runner stalled somewhere in a 25 ms window. That is the pre-existing real-time-sensitive reap test (TIMEOUT_MS = 50, sleep(40)/sleep(25) margins), the same CI-only failure class the comment atop relay/vitest.config.ts documents; nothing in this branch touches alarms or timing, and the untouched re-run passed. Left alone here as out of scope, but it will flake again on a slow enough runner.

@karngyan
karngyan merged commit 59040de into main Aug 9, 2026
1 of 2 checks passed
@karngyan
karngyan deleted the fix/test-log-noise branch August 9, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant